#ifndef ASCII_HEADER
#define ASCII_HEADER

// this header needs
#include <stdio.h>
#include "../ARRAY.h"
// #include "UNICD.h" (see down below!)

// typedefs
typedef umax ascii_int; // ASCII integer representation
// the integer representation is the same as the encoded representation

// https://en.wikipedia.org/wiki/ASCII
#define MIN_ASCII_INT 0x00
#define MAX_ASCII_INT 0x7F
#define INV_ASCII_INT 0xFF
#define INV_ASCII_INT_STR "[INV_ASCII_INT]"
#define INV_ENC_ASCII_STR "[INV_ENC_ASCII]"

// ASCII character table
#define ASCII_INT_CHAR_TB_LENGTH 0x80
ascii_int ASCII_INT_CHAR_TB[ASCII_INT_CHAR_TB_LENGTH] = {
  /* 0x00 */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, '\a', '\b', '\t', '\n', '\v', '\f', '\r', 0x0E, 0x0F, 
  /* 0x10 */ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 
  /* 0x20 */ ' ',  '!',  '"',  '#',  '$',  '%',  '&',  '\'', '(',  ')',  '*',  '+',  ',',  '-',  '.',  '/', 
  /* 0x30 */ '0',  '1',  '2',  '3',  '4',  '5',  '6',  '7',  '8',  '9',  ':',  ';',  '<',  '=',  '>',  '?', 
  /* 0x40 */ '@',  'A',  'B',  'C',  'D',  'E',  'F',  'G',  'H',  'I',  'J',  'K',  'L',  'M',  'N',  'O', 
  /* 0x50 */ 'P',  'Q',  'R',  'S',  'T',  'U',  'V',  'W',  'X',  'Y',  'Z',  '[',  '\\', ']',  '^',  '_', 
  /* 0x60 */ '`',  'a',  'b',  'c',  'd',  'e',  'f',  'g',  'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o', 
  /* 0x70 */ 'p',  'q',  'r',  's',  't',  'u',  'v',  'w',  'x',  'y',  'z',  '{',  '|',  '}',  '~',  0x7F
};

// table definitions
#define ASCII_INT_CTRL_CHARS_START  0x00
#define ASCII_INT_CTRL_CHARS_END    0x19
#define ASCII_INT_PRINT_CHARS_START 0x20
#define ASCII_INT_PRINT_CHARS_END   0x7F
#define ASCII_INT_COMMA             0x2C
#define ASCII_INT_NEWLN             0xA0
#define ASCII_INT_WHITESPACE_LENGTH 6
ascii_int ASCII_INT_WHITESPACE[ASCII_INT_WHITESPACE_LENGTH] =
{
  '\t', // 0x09 (horizontal tab)
  '\n', // 0x0A (line feed)
  '\v', // 0x0B (vertical tab)
  '\f', // 0x0C (form feed)
  '\r', // 0x0D (carriage return)
  ' '   // 0x20 (space)
};

#define ASCII_INT_NUMBER_BEGIN 0
#define ASCII_INT_NUMBER_HEX_UPPER_BEGIN 10
#define ASCII_INT_NUMBER_HEX_LOWER_BEGIN 16
#define ASCII_INT_NUMBER_PMDX_BEGIN 22
#define ASCII_INT_NUMBER_LENGTH 26
ascii_int ASCII_INT_NUMBER[ASCII_INT_NUMBER_LENGTH] =
{
  /* 0x30 */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', // octal/decimal
  /* 0x41 */ 'A', 'B', 'C', 'D', 'E', 'F',                     // hex uppercase
  /* 0x61 */ 'a', 'b', 'c', 'd', 'e', 'f',                     // hex lowercase
  // other usual chars
  /* 0x2B */ '+',
  /* 0x2D */ '-',
  /* 0x2E */ '.',
  /* 0x78 */ 'x'
};

// checking
byte check_ascii_int(ascii_int ch);
byte check_enc_ascii(void * src, umax ssize);
// get/write (the best duo)
ascii_int get_ascii_int(void * src, umax ssize);
void * write_enc_ascii(ascii_int ch, void * dest, umax dsize);
// printing
byte print_ascii_int(ascii_int ch);
byte print_enc_ascii(void * src, umax ssize);

// unicode conversion related (for compatibility with CHAR_ARR functions)

// important header position!!!
#include "UNICD.h"

// checking
byte check_ascii_as_unicd(ascii_int ch);
bool check_unicd_as_ascii(unicd_int ch);
// getting
unicd_int get_ascii_as_unicd(ascii_int ch);
ascii_int get_unicd_as_ascii(unicd_int ch);

#include "ASCII.c"

#endif // ASCII_HEADER
